home *** CD-ROM | disk | FTP | other *** search
- ---EXPR.DOC---
-
- Overview of Expressions
- -------- -- -----------
-
- Most of the operands that you code into your instructions and data
- initializations will be simple register names, variable names, or constants.
- However, you will regularly wish to code operands that are the results of
- an arithmetic calculation, performed either by the machine when the program
- is running (for indexing), or by the assembler (to determine the value to
- assemble into the program). A86 has a full set of operators that you can use
- to create expressions to cover these cases:
-
- * Arithmetic Operators
- byte isolation and combination (HIGH, LOW, BY)
- addition and subtraction (+,-)
- multiplication and division (* , /, MOD)
- shifting operators (SHR, SHL, BIT)
-
- * Logical Operators
- (AND, OR, XOR, NOT)
-
- * Relational Operators
- (EQ, LE, LT, GE, GT, NE)
-
- * Attribute Operators/Specifiers
- size specifiers (B=BYTE,W=WORD,F=FAR,SHORT,LONG)
- attribute specifiers (OFFSET,NEAR,brackets)
- segment-addressing specifier (:)
- compatibility operators (PTR,ST)
- built-in value specifiers (TYPE,THIS,$)
-
- * Special Data Duplication Operator
- (DUP) --see DB_DW_DD.DOC for a description
-
-
- Types of Expression Operands
- ----- -- ---------- --------
-
- Numbers and Label Addresses
-
- A number or constant (16-bit number) can be used in most expressions. A label
- (defined with a colon) is also treated as a constant and so can be used in
- expressions, except when it is a forward reference.
-
-
- Variables
-
- A variable stands for a byte- or word-memory location. You may add or subtract
- constants from variables; when you do so, the constant is added to the address
- of the variable. You typically do this when the variable is the name of a
- memory array.
-
-
- Index Expressions
-
- An index expression consists of a combination of a base register [BX] or
- [BP], and/or an index register [SI] or [DI], with an optional constant added or
- subtracted. You will usually want to precede the bracketed expression with
- B, W, or F; to specify the kind of memory unit (byte, word, or far-pointer)
- you are referring to. The expression stands for the memory unit whose address
- is the run-time value(s) of the base and/or index registers added to the
- constant. See EFF_ADDR.DOC for more details on indexed memory.
-
-
- Arithmetic Operators
- ---------- ---------
- HIGH/LOW
-
- Syntax: HIGH operand
- LOW operand
-
- These operators are called the "byte isolation" operators. The operand must
- evaluate to a 16-bit number. HIGH returns the high-order byte of the number;
- LOW the low-order byte.
-
- For example,
-
- MOV AL,HIGH(01234) ; AL = 012
- TENHEX EQU LOW(0FF10) ; TENHEX = 010
-
- These operators can be applied to each other. The following identities apply:
-
- LOW LOW Q = LOW Q
- LOW HIGH Q = HIGH Q
- HIGH LOW Q = 0
- HIGH HIGH Q = 0
-
-
- BY
-
- Syntax: operand BY operand
-
- This operator is a "byte combination" operator. It returns the word whose
- high byte is the left operand, and whose low byte is the right operand. For
- example, the expression 3 BY 5 is the same as hexadecimal 0305. The BY
- operator is exclusive to A86. I added it to cover the following situation:
- Suppose you are initializing your registers to immediate values. Suppose
- you want to initialize AH to the ASCII value 'A', and AL to decimal 10. You
- could code this as two instructions MOV AH,'A' and MOV AL,10; but you realize
- that a single load into the AX register would save both program space and
- execution time. Without the BY operator, you would have to code MOV AX,0410A,
- which disguises the types of the individual byte-operands you were thinking
- about. With BY, you can code it properly: MOV AX,'A' BY 10.
-
-
- Addition (combination)
-
- Syntax: operand + operand
- operand.operand
- operand PTR operand
- operand operand
-
- As shown in the above syntax, addition can be accomplished in four ways: with a
- plus sign, with a dot operator, with a PTR operator, and simply by juxtaposing
- two operands next to each other. The dot and PTR operators are provided for
- compatibility with Intel/IBM assemblers. The dot is used in structure-field
- notation; PTR is used in expressions such as BYTE PTR 0. (See COMPAT.DOC
- for recommendations concerning PTR.)
-
- If either operand is a constant, the answer is an expression with the typing of
- the other operand, with the offsets added. For example, if BVAR is a byte
- variable, then BVAR + 100 is the byte variable 100 bytes beyond BVAR.
-
- Other examples:
- DB 100+17 ; simple addition
- CTRL EQU -040
- MOV AL,CTRL'D' ; juxtaposition provides a nice notation for control-D!
- MOV DX,[BP].SMEM ; --where SMEM was declared in an unindexed structure
-
-
- Subtraction
-
- Syntax: operand - operand
-
- The subtraction operator may have operands that are:
-
- a. both absolute numbers
- b. variable names that have the same type
-
- The result is an absolute number; the difference between the two operands.
-
-
- Multiplication and Division
-
- Syntax:
- Multiplication: operand * operand
- Division: operand / operand
- Modulo: operand MOD operand
-
- You may only use these operators with absolute numbers, and the result is always
- an absolute number. Either operand may be a numeric expression, as long as the
- expression evaluates to an absolute number. Examples:
-
- CMP AL, 2 * 4 ; compare AL to 8
- MOV BX, 0123/16 ; BX = 012
-
-
- Shifting Operators
-
- Syntax: Shift right: operand SHR count
- Shift left: operand SHL count
- Bit number: BIT count
-
- The shift operators will perform a "bit-wise" shift of the operand. The operand
- will be shifted "count" bits either to the right or the left. Bits shifted into
- the operand will be set to 0.
-
- The expression "BIT count" is equivalent to "1 SHL count"; i.e., BIT returns
- the mask of the single bit whose number is "count". The operands must be
- numeric expressions that evaluate to absolute numbers. Examples:
-
- MOV BX, 0FACBH SHR 4 ; BX = 0FACH
- OR AL,BIT 6 ; AL = AL OR 040 -- 040 is the mask for bit number 6
-
-
- Logical Operators
- ------- ---------
- Syntax: operand OR operand
- operand XOR operand
- operand AND operand
- NOT operand
-
- The logical operators may only be used with absolute numbers. They always
- return an absolute number.
-
- Logical operators operate on individual bits. Each bit of the answer depends
- only on the corresponding bit in the operand(s).
-
- The functions performed are as follows:
-
- 1. OR: An answer bit is 1 if either or both of the operand bits is 1. An
- answer bit is 0 only if both operand bits are 0. Example:
-
- 11110000xB OR 00110011xB = 11110011xB
-
-
- 2. XOR: This is "exclusive OR." An answer bit is 1 if the operand bits are
- different; an answer bit is 0 if the operand bits are the same. Example:
-
- 11110000xB XOR 00110011xB = 11000011xB
-
-
- 3. AND: An answer bit is 1 only if both operand bits are 1. An answer bit is
- 0 if either or both operand bits are 0. Example:
-
- 11110000xB AND 00110011xB = 00110000xB
-
- 4. NOT: An answer bit is the opposite of the operand bit. It is 1 if the
- operand bit is 0; 0 if the operand bit is 1. Example:
-
- NOT 00110011xB = 11001100xB
-
-
- Relational Operators
- ---------- ---------
- Syntax:
- equal: operand EQ operand
- not equal: operand NE operand
- less than: operand LT operand
- less or equal: operand LE operand
- greater than: operand GT operand
- greater or equal: operand GE operand
-
- The relational operators may have operands that are:
-
- a. both absolute numbers
- b. variable names that have the same type
-
- The result of a relational operation is always an absolute number. They return
- an 8-or 16-bit result of all 1's for TRUE and all 0's for FALSE. Examples:
-
- MOV AL, 3 EQ 0 ; AL = 0 (false)
- MOV AX, 2 LE 15 ; AX = 0FFFFH (true)
-
-
- Attribute Operators/Specifiers
- --------- --------------------
- B,W,F memory-variable specifiers
-
- Syntax: B operand
- operand B
- W operand
- operand W
- F operand
- operand F
-
- B, W, and F convert the operand into a BYTE, WORD, and DOUBLEWORD variable,
- respectively. The operand can be a constant, or a variable of the other type.
- Examples:
-
- ARRAY_PTR:
- DB 100 DUP (?)
- WVAR DW ?
- MOV AL,ARRAY_PTR B ; loads the first byte of ARRAY_PTR array into AL
- MOV AL,WVAR B ; load the low byte of WVAR into AL
- MOV AX,W[01000] ; load AX with the memory-word at location 01000
- LDS BX,F[01000] ; load DS:BX with the doubleword at location 01000
-
- For compatibility with Intel/IBM assemblers, A86 accepts the more verbose
- synonyms BYTE, WORD, and FAR for B,W,F, respectively.
-
-
- SHORT and LONG operators
-
- Syntax: SHORT label
- LONG label
-
- The SHORT operator is used to specify that the label referenced by a JMP
- instruction is within 127 bytes of the end of the instruction. The LONG
- operator specifies the opposite: that the label is not within 127 bytes. The
- appropriate operator can (and sometimes must) be used if the label is forward
- referenced in the instruction.
-
- When a non-local label is forward referenced, the assembler assumes that it will
- require two bytes to represent the relative offset of the label. By correctly
- using the SHORT operator, you can save a byte of code when you use a forward
- reference. If the label is not within the specified range, an error will occur.
- The following example illustrates the use of the SHORT operator.
-
- JMP FWDLAB ;three byte instruction
- JMP SHORT FWDLAB ;two byte instruction
- JMP >L1 ; two byte instruction automatically assumed for a local label
-
- Because the assembler assumes that a forward-reference local label is SHORT,
- you may sometimes be forced to override this assumption if the label is in fact
- not within 127 bytes of the JMP. This is why LONG is provided:
-
- JMP LONG >L9 ; three byte instruction
-
- NOTE that LONG will have effect only on the operand to an unconditional JMP
- instruction; not to conditional jumps. This is because the conditional jumps
- don't have 3-byte forms; the only conditional jumps are short ones. If you
- run into this problem, then chances are your code is getting out of control--
- time to rearrange, or to break off some of the intervening code into separate
- procedures. If you insist upon leaving the code intact, you can replace the
- conditional jump with an "IF cond JMP".
-
-
- OFFSET operator
-
- Syntax: OFFSET var-name
-
- OFFSET is used to convert a variable into the constant pointer to the variable.
- For example, if you have declared XX DW ?, and you want to load SI with the
- pointer to the variable XX, you can code: MOV SI,OFFSET XX. The simpler
- instruction MOV SI,XX moves the variable contents of XX into SI, not the
- constant pointer to XX.
-
-
- NEAR Operator
-
- Syntax: NEAR operand
-
- NEAR converts the operand to have the type of a code label, as if it were
- defined by appearing at the beginning of a program line with a colon after it.
- NEAR is provided mainly for compatibility with Intel/IBM assemblers.
-
- Square Brackets Operator
-
- Syntax: [operand]
-
- Square brackets around an operand give the operand a memory-variable type.
- Square brackets are generally used to enclose the names of base and index
- registers: BX, BP, SI, and DI. When the size of the memory variable can be
- deduced from the context of the expression, they are also used to turn numeric
- constants into memory variables. Examples:
-
- MOV B[BX+50],047 ; move immediate value 047 into memory byte at BX+50
- MOV AL,[050] ; move byte at memory loaction 050 into AL
- MOV AL,050 ; move immediate value 050 into AL
-
-
- Colon Operator
-
- Syntax: constant:operand
- segreg:operand
-
- The colon operator is used to attach a segment-register value to an operand.
- The segment-register value appears to the left of the colon; the rest of the
- operand appears to the right of the colon.
-
- There are two forms to the colon operator. The first form has a constant as
- the segment-register value. This form is used to create an operand to a long
- (inter-segment) JMP or CALL instruction. An example of this is the instruction
- JMP 0FFFF:0, which jumps to the cold-boot reset location of the 86 processor.
-
- The only context other than JMP or CALL in which this first form is legal, is as
- the operand to a DD directive or an EQU directive. The EQU case has a further
- restriction: the offset (the part to the right of the colon) must have a value
- less than 256. This is becuase there simply isn't room in a symbol-table entry
- for a segment-register value AND a 2-byte offset. I don't think you will be
- hurt by this restriction, since references to other segments are usually to
- jump-tables at the beginning of those segments.
-
- The second form has a segment register name to the left of the colon. This
- is the segment-oveeride form, provided for compatibility with Intel/IBM
- assebmlers. A86 will generate a segment-override byte when it sees this
- form, unless the operand to the right of the colon already has a default
- segment register that is the same as the given override.
-
- I prefer the more explicit method of overrides, exclusive to A86: simply place
- the segment register name before the instruction mnemonic. For example, I
- prefer ES MOV AL,[BX] to MOV AL,ES:[BX].
-
-
- ST Operator
-
- ST is ignored whenever it occurs in an expression. It is provided for
- compatibility with Intel and IBM assemblers.
-
- TYPE Operator
-
- Syntax: TYPE operand
-
- The TYPE operator returns 1 if the operand is a byte variable; 2 if the operand
- is a word variable; 4 if the operand is a doubleword variable; and the number
- of bytes allocated by the strucure if the operand is a structure name.
-
-
- THIS and $ Specifiers
-
- THIS returns the value of the current location counter. It is provided for
- compatibility with Intel/IBM assemblers. The dollar-sign $ is the more
- standard and familiar specifier for this purpose; it is equivalent to THIS
- NEAR. THIS is typically used with the BYTE and WORD specifiers to create
- alternate-typed symbols at the same memory location:
-
- BVAR EQU THIS BYTE
- WVAR DW ?
-
- I don't recommend the use of THIS. If you wish to retain Intel-compatibility,
- you can use the less-verbose LABEL directive:
-
- BVAR LABEL BYTE
- WVAR DW ?
-
- If you are not concerned with compatibility to lesser assemblers, A86 offers
- a variety of less-verbose forms. The most concise is DB without an operand:
-
- BVAR DB
- WVAR DW ?
-
- If this is too cryptic for you, there is always BVAR EQU B[$].
-
-
- Operator Precedence
- -------- ----------
- Consider the expression 1 + 2 * 3. When A86 sees this expression, it could
- perform the multiplication first, giving an answer of 1+6 = 7; or it could do
- the addition first, giving an answer of 3*3 = 9. In fact, A86 does the
- multiplication first, because A86 assigns a higher precedence to multiplication
- than it does addition.
-
- The following list specifies the order of precedence A86 assigns to
- expression operators. All expressions are evaluated from left to right
- following the precedence rules. You may override this order of evaluation and
- precedence through the use of parentheses (). In the example above, you could
- override the precedence by parenthesizing the addition: (1+2) * 3.
-
- Some symbols that we have referred to as operators, are treated by the
- assembler as operands having built-in values. These include B, W, F, $, and
- ST.
-
- If two operators are adjacent, the rightmost operator must have precedence;
- otherwise, parentheses must be used.
-
- ---Highest Precedence---
-
- 1. Parenthesized expressions
- 2. Period
- 3. OFFSET, TYPE, and PTR
- 4. HIGH, LOW, and BIT
- 5. Multiplication and division: *, /, MOD, SHR, SHL
- 6. Addition and subtraction: +,-
- a. unary
- b. binary
- 7. Relational: EQ, NE, LT, LE, GT, GE
- 8. Logical NOT
- 9. Logical AND
- 10. Logical OR and XOR
- 11. Colon, SHORT, LONG, and BY
- 12. DUP
-
- ---Lowest Precedence---
-